<?php

declare(strict_types=1);

namespace App\Core;

final class CSRF
{
    private const SESSION_KEY = '_csrf_token';

    public static function token(): string
    {
        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }
        if (empty($_SESSION[self::SESSION_KEY]) || !is_string($_SESSION[self::SESSION_KEY])) {
            $_SESSION[self::SESSION_KEY] = bin2hex(random_bytes(32));
        }
        return $_SESSION[self::SESSION_KEY];
    }

    public static function input(): string
    {
        $token = htmlspecialchars(self::token(), ENT_QUOTES, 'UTF-8');
        return '<input type="hidden" name="_token" value="' . $token . '">';
    }

    public static function check(?string $token): bool
    {
        if (!is_string($token) || $token === '') {
            return false;
        }
        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }
        $stored = $_SESSION[self::SESSION_KEY] ?? '';
        return is_string($stored) && hash_equals($stored, $token);
    }

    public static function field(): string
    {
        return self::input();
    }

    public static function validateOrAbort(): void
    {
        $token = $_POST['_token'] ?? '';
        if (!self::check(is_string($token) ? $token : '')) {
            http_response_code(419);
            echo 'Invalid CSRF token';
            exit;
        }
    }
}
